/*
 * @Title: DataAdjust.java
 * @Package tbg
 * @Description: TODO
 * @author tbc
 * @date 2016年6月11日 上午2:12:45
 * @version
 */
package tbg;

import net.tt.util.CloseUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import tbg.util.MonthEnum;

import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 数据调整
 * F:\\Users\\tbc\\Desktop\\东风小康出口发运信息.xlsx
 * F:\\Users\\tbc\\Desktop\\哈.xlsx
 *
 * @author tbc
 * @version 1.0 create:{2016年6月11日 上午2:12:45}
 */
public class DataAdjust2 {

    private static XSSFWorkbook wb;
    private static XSSFSheet sheet;

    // 默认随机数范围1-3
    private static int scope = 3;
    private static int rows = 50;// 默认修改50行
    private static int amount;
    // 数量所在列的序号
    private static int numIndex = 0;

    public static void main(String[] args) throws InterruptedException {
        System.out.println("输入要修改的行数(直接回车将默认50行):");

        String from = "";
        @SuppressWarnings("resource")
        Scanner s = new Scanner(System.in);
        int tempIn = 0;
        while (true) {
            String str = s.nextLine();
            //
            if (tempIn == 0) {
                if (str != null && !"".equals(str)) {
                    rows = Integer.parseInt(str);
                }
                System.out.println("将要修改的行数设定为： " + rows);
                System.out.println("设置随机数范围（只输入一个最大值即可,默认为3）：");
                tempIn++;
                continue;
            }
            //
            if (tempIn == 1) {
                if (str != null && !"".equals(str)) {
                    scope = Integer.parseInt(str);
                }
                System.out.println("随机数范围最大： " + scope);
                System.out.println("设置要修改的数量总数：");
                tempIn++;
                continue;
            }
            //
            if (tempIn == 2) {
                try {
                    amount = Integer.parseInt(str);
                } catch (Exception e) {
                    System.out.println("要修改的数量总数不能为空,重新输入：");
                    continue;
                }
                System.out.println("将要修改的数量总数为： " + amount);
                System.out.println("拖动文件到命令窗口（或者输入完整文件路径及名称）：");
                tempIn++;
                continue;
            }
            if (tempIn == 3) {
                from = str;
                break;
            }

        }

        System.out.println("--> 开始程序初始化 ...");
        // 初始化
        init(from);
        System.out.println("初始化完成");
        System.out.println("随机获取 " + rows + " 条记录...");
        List<Integer> proRows = getProRows();
        System.out.println("--> 随机获取 " + rows + " 条记录完成");
        System.out.println("开始随机调整数量...");
        //
        if (amount <= 0) {
            // 总数减
            process2(proRows);
        } else {
            // 总数加
            process(proRows);
        }

        System.out.println("--> 调整完成");

        System.out.println("删除数量为0的行...");
        deleteRowByZero();
        System.out.println("--> 删除数量为0的行成功");

        System.out.println("数据写回excel...");
        //
        write(from);
        System.out.println("--> 完成");
        System.out.println("清理资源，程序将退出...");

    }

    public static void init(String from) throws InterruptedException {
        if (from.startsWith("\"")) {
            System.out.println("文件路径带引号，尝试去除...");
            from = from.substring(1, from.length() - 1);
        }
        System.out.println("--> 正在加载文件：" + from);
        // 输入流应该啥时候关闭。。。？？？
        InputStream in = null;
        try {
            in = new FileInputStream(from);
            System.out.println("--> 加载成功，创建工作簿对象...");
            wb = new XSSFWorkbook(in);
            System.out.println("--> 工作簿对象创建完成");
        } catch (FileNotFoundException e) {
            System.out.println("读取文件失败，文件不存在或者文件名有特殊符号。。。最好是只有英文字母");
            System.out.println("程序自动退出，修改文件路径或者文件名再试试");
            TimeUnit.SECONDS.sleep(2);
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("加载excel失败，不知道为什么 ，程序退出。。。");
            System.out.println(e.getMessage());
            TimeUnit.SECONDS.sleep(2);
        }
        System.out.println("--> 读取sheet页");
        try {
            sheet = wb.getSheetAt(0);
            // 全都找sheet "1"
            // sheet = wb.getSheet("1");
            if (sheet == null) {
                System.out.println("读取sheet页失败...");
                TimeUnit.SECONDS.sleep(2);
                System.exit(0);
            }
        } catch (Exception e) {
            System.out.println();
        }

        // int numIndex = 0;
        XSSFRow row0 = sheet.getRow(0);
        for (int i = 0; i < row0.getLastCellNum(); i++) {
            Cell cel = row0.getCell(i);
            // 标题要叫数量或者销量
            List<String> ls = Arrays.asList("数量", "销量");
            if (ls.contains(cel.getStringCellValue())) {
                numIndex = i;
            }
        }

    }

    /**
     * 随机指定数量的记录（序号）
     *
     * @author tbc
     * @version 1.0 create:{2016年6月11日 上午2:55:53}
     */
    public static List<Integer> getProRows() {

        // 随机足够数量的记录，标号缓存在List
        List<Integer> rowsIndex = new ArrayList<>();
        for (int i = 0; i < rows; i++) {
            int lastrow = sheet.getLastRowNum();
            while (true) {
                int t = getRandom(lastrow);
                if (rowsIndex.contains(t) || t == 0) {
                    continue;
                } else {
                    rowsIndex.add(t);
                    break;
                }
            }
        }

        return rowsIndex;

    }

    /**
     * @author tbc
     * @version 1.0 create:{2016年6月11日 上午3:00:07}
     */
    public static void process(List<Integer> rowsIndex) {
        // 定义一个变量，记录已经增加的总数量
        int temp = 0;
        for (int i = 0; i < rows; i++) {
            if (temp >= amount) {
                break;
            }
            XSSFRow row = sheet.getRow(rowsIndex.get(i));
            XSSFCell cell = row.getCell(numIndex);
            double value = cell.getNumericCellValue();
            int random = getRandom(scope);
            value += random;
            temp += random;
            cell.setCellValue(value);
        }
        if (temp < amount) {
            amount -= temp;
            process(rowsIndex);
        }

    }

    public static void process2(List<Integer> rowsIndex) {
        // 定义一个变量，记录已经增加的总数量
        int temp = 0;
        for (int i = 0; i < rows; i++) {
            if (temp <= amount) {
                break;
            }
            XSSFRow row = sheet.getRow(rowsIndex.get(i));
            XSSFCell cell = row.getCell(numIndex);
            double value = cell.getNumericCellValue();
            int random = getRandom(scope);
            value -= random;
            temp -= random;
            cell.setCellValue(value);
        }
        // if (temp > amount) {
        // amount -= temp;
        // process(rowsIndex);
        // }

    }

    public static void write(String path) throws InterruptedException {

        OutputStream out = null;
        try {
            out = new FileOutputStream(path);
            //
            wb.write(out);
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            TimeUnit.SECONDS.sleep(2);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.close(out);
        }
    }

    /**
     * 这个方法还有问题 - 2016年06月11日 16:54:03
     *
     * @author tbc
     * @version 1.0 create:{2016年6月11日 下午4:53:54}
     */
    public static void deleteRowByZero() {
        int i = sheet.getLastRowNum();
        XSSFRow row;
        while (i > 1) {
            i--;
            row = sheet.getRow(i);
            XSSFCell cell = row.getCell(numIndex);
            System.out.println("...cell raw : " + cell.getRawValue());
            if (cell.getNumericCellValue() == 0.0) {
                // 这个方法可以把startRow至endRow之间的所有行，按照n向上或移动。
                // n如果为正数，则整体区域向下移动，
                // n如果为负数，则整体区域向上移动，
                // 我们如果要删除空行，就可以利用shiftRows方法，从sheet表的最后一行开始向上逆序移动非空行。
                System.out.println("删除第" + i + "行 ");
                // sheet.removeRow(row);
                sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
            }
        }
        copySheet();
        // 可以删除原sheet页
        wb.removeSheetAt(wb.getSheetIndex(sheet));
        //
        minusSheet(wb);
    }

    // 删除多余的sheet页
    public static void minusSheet(XSSFWorkbook wb) {
//        wb.getSheet("Sheet2");
        XSSFSheet sheet2 = wb.getSheet("Sheet2");
        int s2 = wb.getSheetIndex(sheet2);
        XSSFSheet sheet3 = wb.getSheet("Sheet3");
        int s3 = wb.getSheetIndex(sheet2);
        wb.removeSheetAt(s2);
        wb.removeSheetAt(s3);
    }

    public static XSSFSheet copySheet() {
        String sheetName = MonthEnum.getCn(Integer.parseInt(DateTime.now().toString("MM")));
        XSSFSheet _sheet = wb.createSheet(sheetName);
        for (int i = 0; i <= sheet.getLastRowNum(); i++) {
            XSSFRow row = sheet.getRow(i);
            XSSFRow _row = _sheet.createRow(i);
            for (int j = 0; j < row.getLastCellNum(); j++) {
                XSSFCell cell = row.getCell(j);
                XSSFCell _cell = _row.createCell(j);
                if (cell == null) {
                    _cell.setCellValue("");
                } else {
                    if (cell.getCellType() == 1) {
                        _cell.setCellValue(cell.getStringCellValue());
                    } else if (cell.getCellType() == 0) {
                        // 数值类型
                        _cell.setCellValue(toDouble(cell.getRawValue()));
                    } else {
                        _cell.setCellValue(cell.getRawValue());
                    }
                }
            }
        }
        return _sheet;
    }

    private static int getRandom(int max) {
        Random r = new Random();
        // 大于等于0小于n
        return r.nextInt(max) + 1;
    }

    private static double toDouble(String source) {
        return toDouble(source, 0.0);
    }

    private static double toDouble(String source, Double def) {
        try {
            return Double.parseDouble(source);
        } catch (Exception e) {
            return def;
        }
    }
}
